#include "mlp_layer.h"
#ifndef MLP_NEURAL_NETWORK_H
#define MLP_NEURAL_NETWORK_H

struct MLPNeuralNetwork;
typedef struct MLPNeuralNetwork *MLPNeuralNetworkPtr;

typedef double (*LossFunctionType)(const double y_true[], const double y_pred[], int n_classes);
typedef void (*LossFnDiffType)(double loss, const double y_true[], const double y_pred[], double delta_pred[], int n_classes);

MLPNeuralNetworkPtr InitNeuralNetwork();
void DeinitNeuralNetwork(MLPNeuralNetworkPtr *ptr);

void AppendLayer(MLPNeuralNetworkPtr p_nn, int input_dim, int output_dim, 
    ActivateType activate, DiffActivateType activate_diff);


/**
 * @brief 采用SGD训练MPL神经网络
 * 
 * @param nn_ptr: 神经网络实例
 * @param loss_fn: 损失函数
 * @param loss_diff_fn: 损失函数的导函数
 * @param x: 数据的特征
 * @param y: 数据的预测目标
 * @param n_samples: 样本数量
 * @param n_classes: 预测类别数量
 * @param epochs: 训练轮次
 * @param lr: 学习率
 * 
 * @return: 训练过程中的损失记录
 */
double *TrainNeuralNetwork(MLPNeuralNetworkPtr const nn_ptr, 
    LossFunctionType loss_fn,
    LossFnDiffType loss_diff_fn,
    double **x, double **y, int n_samples, int n_classes,
    int epochs, double lr);


void Inference(MLPNeuralNetworkPtr nn_ptr, double x[], double p[], int n_classes);

void PrintParameters(MLPNeuralNetworkPtr nn_ptr);
#endif

